package com.ps.service.dept.imp;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.opensymphony.xwork2.util.ArrayUtils;
import com.ps.dao.BaseDaoSupport;
import com.ps.dao.dept.DepartmentDAO;
import com.ps.dao.dept.WorkPositionDAO;
import com.ps.dao.person.EmployeeDAO;
import com.ps.dao.setting.AreaDAO;
import com.ps.entity.Result;
import com.ps.entity.Status;
import com.ps.global.Globals;
import com.ps.global.ResultCode;
import com.ps.pojo.dept.Department;
import com.ps.pojo.dept.WorkPosition;
import com.ps.pojo.person.Employee;
import com.ps.service.BaseServiceSupport;
import com.ps.service.dept.DepartmentService;
import com.ps.util.Kit;
import com.ps.util.R;
import com.ps.view.tree.Item;
import com.ps.view.tree.Tree;

public class DepartmentServiceImp extends BaseServiceSupport<Department>
		implements DepartmentService {
	@Autowired
	private DepartmentDAO departmentDAO;
	
	@Autowired
	private WorkPositionDAO workPositionDAO;

	
	@Autowired
	private EmployeeDAO employeeDAO;
	
	
	@Autowired
	private AreaDAO areaDAO;
	@Override
	public BaseDaoSupport<Department> getBaseDao() {
		// TODO Auto-generated method stub
		return departmentDAO;
	}

	public Result addDepartment(Department department) {
		Result result = this.save(department);
		result.setDatas(department.getDepartmentId());
		return result;
	}

	public Result addDepartment(Department department, Integer[] wpIds) {
		if (departmentDAO.getCountByProperty("name", department.getName()) > 0) {
			Result result = Kit.createResult();
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("nameCantRepeat"));
			return result;
		}
		
		
		if (ArrayUtils.isEmpty(wpIds)) {
			Result result = this.save(department);
			result.getStatus().setCode(ResultCode.ADD_SUCCES);
			return result;
			
		}
		Result result = Kit.createResult();
		Session session = departmentDAO.getHibernateTemplate().getSessionFactory().openSession();
		Transaction tx  = session.beginTransaction();
		try {
			session.save(department);

	        String hql = "UPDATE WorkPosition SET department.departmentId = " + department.getDepartmentId() + " WHERE wpId = ?";
	        Query query = session.createQuery(hql);
	        	
	        for (Integer wpId : wpIds) {
	        	query.setInteger(0, wpId);
	            query.executeUpdate();
	        }
	        tx.commit();
	        result.getStatus().setCode(ResultCode.ADD_SUCCES);
	        result.setDatas(department.getDepartmentId());
	        result.getStatus().setMessage(R.string.getProperty("addsucces"));
		} catch (Exception e) {
			if (tx != null) tx.rollback();
			if (session != null) session.close();
			log.error("addDepartment exception ", e);
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("addfail"));
		}
		
		return result;
	}

	public Result deleteDepartment(Integer departmentId, Integer inputerId) {
		Result result = this.delete(departmentId);

		try {
			/**
			 * 此处需要添加日志记录
			 */

		} catch (Exception e) {
			log.error("delDepartment exception ", e);

		}
		return result;

	}

	public Result queryDepartmentDetail(final Integer departmentId) {

        
		final Department dept = departmentDAO.findById(departmentId);
		
		Result result = Kit.createResult();
		if (dept != null) {
			com.ps.entity.dept.Department eDept = new com.ps.entity.dept.Department();
	        Employee emp  = employeeDAO.findById(dept.getInputerId());
	        eDept.setInputerName(emp.getUserName());
			List<WorkPosition> list =  workPositionDAO.findByProperty("department", dept);
			BeanUtils.copyProperties(dept, eDept);
			for (WorkPosition wp : list) {
				com.ps.entity.dept.WorkPosition eWp = new com.ps.entity.dept.WorkPosition();
				BeanUtils.copyProperties(wp, eWp, new String []{"department"});
				
				eDept.getWorkPositions().add(eWp);
			}
			
			
			result.setDatas(eDept);
		} else {
			result.getStatus().setCode(Status.EMPTY);
			result.getStatus().setMessage(R.string.getProperty("queryempty"));
		}
		return result;
	}

	public Result updateDepartment(Department department) {
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
		detachedCriteria.setProjection(Projections.count("name"));
		detachedCriteria.add(Restrictions.eq("name", department.getName()));
		detachedCriteria.add(Restrictions.ne("departmentId", department.getDepartmentId()));
		Integer count = (Integer) departmentDAO.getHibernateTemplate().findByCriteria(detachedCriteria).get(0);
		
		if (count > 0) {
			Result result = Kit.createResult();
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("nameCantRepeat"));
			return result;
		}	
        Result result  = this.update(department);
        if (StringUtils.equals(result.getStatus().getCode(), Status.SUCCES)) {
        	result.setDatas(department.getDepartmentId());
        	result.getStatus().setCode("UPDATE_" + Status.SUCCES); 
        	
        }	
		return result;
	}
     
	/**
	 * 生成部门树形菜单
	 */
	@SuppressWarnings("unchecked")
	public String findXmlTree(Integer areaId) {
		Tree tree = new Tree();
		tree.setId("0");
		Item item = new Item();
		item.setId("-1");
		item.setOpen("1");
		item.setText(R.string.getProperty("app_name"));

		try {

			findRootItem(item, areaId);

			tree.getItem().add(item);
			return Kit.obj2XmlString(tree);
		} catch (Exception e) {
			log.error("findXmlTree error !", e);
			return Kit.obj2XmlString(tree);
		}
	}

	/**
	 * 填充根节点
	 * 
	 * @return
	 */
	public void findRootItem(Item rootItem, Integer areaId) {
		List<Department> list = null;
		try {
			if (areaId == Globals.ADMIN_JURISDICTIONS) {
				list = this.departmentDAO.findByProperty(
						DepartmentDAO.FATHER_ID, Globals.DEPT_ONE_LEVEL);

			} else {
				DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
				detachedCriteria.add(Restrictions.eq(DepartmentDAO.FATHER_ID, Globals.DEPT_ONE_LEVEL));
				detachedCriteria.add(Restrictions.eq(DepartmentDAO.AREA_ID, areaId));
				list = this.departmentDAO.findByCriteria(detachedCriteria);

			}

			Iterator<Department> iter = list.iterator();
			while (iter.hasNext()) {
				Item item = new Item();
				Department dept = iter.next();
				item.setId(dept.getDepartmentId().toString());
				item.setText(dept.getName());
				findChildItem(item, dept);
				rootItem.getItem().add(item);

			}

		} catch (Exception e) {
			log.error("findRootItem error !", e);
		}

	}

	public void findChildItem(Item levelItem, Department dept) {
		// findChildDept

		Collection<Department> list = dept.getChildDepartments();//findChildDept(dept);
		if (list == null || list.size() == 0) {
			return;
		}

		Iterator<Department> iter = list.iterator();
		while (iter.hasNext()) {
			Item item = new Item();
			Department deptChild = iter.next();
			item.setId(deptChild.getDepartmentId().toString());
			item.setText(deptChild.getName());
			levelItem.getItem().add(item);
			findChildItem(item, deptChild);
		}

	}



	public Collection<Department> findChildDept(final Department dept) {
/*		return departmentDAO.getHibernateTemplate().executeWithNewSession(
				new HibernateCallback<Collection<Department>>() {

					@SuppressWarnings("unchecked")
					public Collection<Department> doInHibernate(Session session)
							throws HibernateException, SQLException {
						session.lock(dept, LockMode.READ);
						return dept.getChildDepartments();
					}
				});*/
		
		return dept.getChildDepartments();
	}

	public boolean existsChild(Integer departmentId) {
		try {
			Department department = departmentDAO.findById(departmentId);
			return department.getChildDepartments() != null
					&& department.getChildDepartments().size() > 0;

		} catch (Exception e) {
			log.error("existsChild exception ", e);
		}

		return false;
	}

	public boolean existsWorkPosition(Integer departmentId) {
		try {
			Department department = departmentDAO.findById(departmentId);
			int count = workPositionDAO.getCountByProperty("department.departmentId", department.getDepartmentId());
			return  count > 0;
		} catch (Exception e) {
			log.error("existsWorkPosition exception ", e);
		}
		return false;
	}
	
	
	

	

	public Result updateDeptWPAndCountPersonIsZero(Department department,
			Integer[] wpIds) {
		
		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Department.class);
		detachedCriteria.setProjection(Projections.count("name"));
		detachedCriteria.add(Restrictions.eq("name", department.getName()));
		detachedCriteria.add(Restrictions.ne("departmentId", department.getDepartmentId()));
		Integer countx = (Integer) departmentDAO.getHibernateTemplate().findByCriteria(detachedCriteria).get(0);
		
		if (countx > 0) {
			Result result = Kit.createResult();
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("nameCantRepeat"));
			return result;
		}			
		
		Result result = Kit.createResult();
	    detachedCriteria = DetachedCriteria.forClass(WorkPosition.class);
		detachedCriteria.add(Restrictions.eq("department.departmentId", department.getDepartmentId()));
		if (ArrayUtils.isNotEmpty(wpIds)) detachedCriteria.add(Restrictions.not(Restrictions.in("wpId", wpIds)));
		
		Session session = workPositionDAO.getHibernateTemplate().getSessionFactory().openSession();
		Transaction tx  = session.beginTransaction();
		try {
			Department tdepartment = (Department) session.get(Department.class, department.getDepartmentId());
			List<WorkPosition> list =  workPositionDAO.findByCriteria(detachedCriteria);
			tdepartment.setName(department.getName());
			tdepartment.setRemark(department.getRemark());
			tdepartment.setArea(areaDAO.findById(department.getAreaId()));
			
            ArrayList<Integer> prWpIds = new ArrayList<Integer> ();
			/*for (WorkPosition wp : list) {
				prWpIds.add(wp.getWpId());
			}*/
			String hql = "SELECT COUNT(employeeId) FROM Employee WHERE workPosition.wpId = ?";
			Iterator<WorkPosition> iter = list.iterator();
			while(iter.hasNext() ) {
				WorkPosition wp  = iter.next();
				Query query = session.createQuery(hql);
				query.setInteger(0, wp.getWpId());
				
				Long count = (Long) query.list().get(0);
				
				System.out.println("count = " + count);
	            if (count == 0 ) {
	            	iter.remove();
		        	wp.setDepartment(null);
		        	session.update(wp);
	            } else {
	            	prWpIds.add(wp.getWpId());
	            }
			}
			
	        if (ArrayUtils.isNotEmpty(wpIds)) {
	        	String hql_ = "UPDATE WorkPosition SET department.departmentId = ? WHERE wpId = ?";
	        	Query query = session.createQuery(hql_);
	        	
	            for (Integer wpId :wpIds) {
	            	query.setInteger(0, department.getDepartmentId());
	            	query.setInteger(1, wpId);
	            	query.executeUpdate();
	            }
	        }
	        session.save(tdepartment);
	        /**
	         * 此处需添加日志记录
	         */
	        tx.commit();

	        
			if (prWpIds.size() == 0) {
		        result.setDatas(department.getDepartmentId());
		        result.getStatus().setCode(ResultCode.UPDATE_SUCCES); 
		        result.getStatus().setMessage(R.string.getProperty("updsucces"));
			} else {
				result.getStatus().setCode(ResultCode.EXISTS_WORK_POSITION_PERSON_UPT);
				result.getStatus().setMessage(R.string.getProperty("exist_work_pos_person_upt"));
				Object [] datas = new Object []{department.getDepartmentId(), prWpIds};
				result.setDatas(datas);
			}			
		} catch (Exception e) {
			if (tx != null) tx.rollback();
			
			log.error("updateDeptWPAndCountPersonIsZero exception ", e);
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("updfail"));
		} finally {
			if (session != null) session.close();
		}
		return result;
	}

	
	
	
	public Result updateDepartment(Department department, Integer[] wpIds) {
		Result result = Kit.createResult();

		DetachedCriteria detachedCriteria = DetachedCriteria.forClass(WorkPosition.class);
		detachedCriteria.add(Restrictions.eq("department.departmentId", department.getDepartmentId()));
		if (ArrayUtils.isNotEmpty(wpIds)) detachedCriteria.add(Restrictions.not(Restrictions.in("wpId", wpIds)));

		Session session = workPositionDAO.getHibernateTemplate().getSessionFactory().openSession();
		Transaction tx  = session.beginTransaction();
		try {
			Department tdepartment = (Department) session.get(Department.class, department.getDepartmentId());
			List<WorkPosition> list =  workPositionDAO.findByCriteria(detachedCriteria);
			tdepartment.setName(department.getName());
			tdepartment.setRemark(department.getRemark());
			tdepartment.setArea(areaDAO.findById(department.getAreaId()));
			
			
	        
	        for (WorkPosition wp : list) {
	        	wp.setDepartment(null);
	        	session.update(wp);
	        }
	        
	        if (ArrayUtils.isNotEmpty(wpIds)) {
	        	String hql = "UPDATE WorkPosition SET department.departmentId = ? WHERE wpId = ?";
	        	Query query = session.createQuery(hql);
	        	
	            for (Integer wpId :wpIds) {
	            	query.setInteger(0, department.getDepartmentId());
	            	query.setInteger(1, wpId);
	            	query.executeUpdate();
	            }
	        }
	        session.save(tdepartment);
	        
	        /**
	         * 此处需添加日志记录
	         */
	        
	        tx.commit();
	        

	        	
	        result.setDatas(department.getDepartmentId());
	        result.getStatus().setCode(ResultCode.UPDATE_SUCCES); 
	        	
	       
	        result.getStatus().setMessage(R.string.getProperty("updsucces"));
		} catch (Exception e) {
			if (tx != null) tx.rollback();
			if (session != null) session.close();
			log.error("updateDepartment exception ", e);
			result.getStatus().setCode(Status.FAIL);
			result.getStatus().setMessage(R.string.getProperty("updfail"));
		}
		


		return result;
	}

}
